15 #define forsn(i, s, n) for (int i = (s); i < (n); i++)
16 #define forn(i, n) forsn (i, 0, n)
17 #define dforn(i, n) for (int i = (n); i-- > 0;)
20 #define ALPHA_VAL(C) ((C) - '0')
21 #define foralpha(x) forn (x, ALPHA_SIZE)
23 typedef unsigned long long int lluint
;
25 typedef const string
*Value
;
27 string
itos(lluint i
, int width
) {
28 if (width
== 0) return "";
30 os
<< setw(width
) << setfill('0') << i
;
34 /**** String register ****/
38 Value
reg_intern(const string
& s
) {
39 return &*_reg
.insert(s
).first
;
49 Node
*children
[ALPHA_SIZE
];
54 #define trie_new() NULL
57 void trie_free(Trie tr
) {
60 trie_free(tr
->children
[dig
]);
65 void _trie_delete_children(Trie tr
) {
66 foralpha (dig
) if (tr
->children
[dig
]) {
67 trie_free(tr
->children
[dig
]);
68 tr
->children
[dig
] = NULL
;
72 void _trie_collapse_children(Trie tr
) {
73 if (!tr
->children
[0] || tr
->children
[0]->value
== Empty
) return;
75 if (!tr
->children
[dig
]) return;
76 if (tr
->children
[dig
]->value
!= tr
->children
[0]->value
) return;
79 tr
->value
= tr
->children
[0]->value
;
80 _trie_delete_children(tr
);
83 // invariante: los valores estan en las hojas
84 void trie_add(Trie
*tr
, const char *s
, Value v
) {
87 foralpha (dig
) (*tr
)->children
[dig
] = NULL
;
92 _trie_delete_children(*tr
);
94 if ((*tr
)->value
!= Empty
) {
96 trie_add(&(*tr
)->children
[dig
], "", (*tr
)->value
);
100 trie_add(&(*tr
)->children
[ALPHA_VAL(*s
)], &s
[1], v
);
102 _trie_collapse_children(*tr
);
106 bool trie_has_children(Trie tr
) {
108 if (tr
->children
[dig
] == NULL
) continue;
114 void trie_debug(Trie tr
, int depth
) {
117 if (!tr
->children
[dig
]) continue;
118 forn (i
, depth
) { cout
<< " "; }
119 cout
<< itos(dig
, 1);
120 if (tr
->children
[dig
]->value
) {
121 cout
<< " (" << *(tr
->children
[dig
]->value
) << ")";
124 trie_debug(tr
->children
[dig
], depth
+ 1);
128 /**** Resultado ****/
130 typedef pair
<string
, Value
> ResultItem
;
131 vector
<ResultItem
> result
;
134 #define _produce(S, V) if ((V) != Invalid) { result.push_back(ResultItem((S), (V))); }
136 char prefix_buf
[Maxlen
];
137 void _build_result_rec(Trie tr
, int prefix_length
) {
138 if (tr
== NULL
) return;
139 if (!trie_has_children(tr
)) {
141 prefix_buf
[prefix_length
] = '\0';
142 _produce(string(prefix_buf
), tr
->value
);
144 // visit the children
146 prefix_buf
[prefix_length
] = '0' + dig
;
147 _build_result_rec(tr
->children
[dig
], prefix_length
+ 1);
152 void trie_print_result(Trie tr
) {
153 Invalid
= reg_intern("invalid");
154 result
= vector
<ResultItem
>();
156 if (!trie_has_children(tr
) && tr
->value
!= Empty
&& tr
->value
!= Invalid
) {
157 // special case: every prefix has the same type
158 printf("%d\n",ALPHA_SIZE
);
160 printf("%d %s\n",dig
,(*tr
->value
).c_str());
163 _build_result_rec(tr
, 0);
165 printf("%d\n",result
.size());
166 forn (i
, (int)result
.size()) {
167 printf("%s %s\n",result
[i
].first
.c_str(),(*result
[i
].second
).c_str());
172 /**** Intervalos ****/
174 #define IMP(X, Y) (!(X) || (Y))
175 void add_interval(Trie
*tr
, int pref_size
, lluint from
, lluint to
, Value val
) {
178 lluint
*from_to
= (t
== 0 ? &from
: &to
);
179 while (pot
> 0 && IMP(t
== 0, from
+ pot
<= to
)) {
180 while (from
+ pot
<= to
&& *from_to
% (pot
* 10) > 0) {
181 string
element(itos(from
/ pot
, pref_size
));
182 trie_add(tr
, element
.c_str(), val
);
194 while (from
+ pot
> to
) { pot
/= 10; pref_size
++; }
198 lluint
atoll_(string s
) {
201 r
= 10 * r
+ ALPHA_VAL(s
[i
]);
218 if (cin
.eof()) break;
226 vector
<InputItem
> todo_list
;
228 // Read the lines and build the todo list
229 forn (line
, nlines
) {
230 string from
, sep
, to
, name
;
231 cin
>> from
>> sep
>> to
>> name
;
233 int k
= from
.size() - to
.size();
235 item
.name_id
= reg_intern(name
);
236 item
.from
= atoll_(from
);
237 item
.to
= atoll_(from
.substr(0, k
) + to
) + 1;
238 item
.pref_size
= from
.size();
240 todo_list
.push_back(item
);
243 // Process the lines in reverse order
244 Trie tr
= trie_new();
246 InputItem
& item(todo_list
[i
]);
247 add_interval(&tr
, item
.pref_size
, item
.from
, item
.to
, item
.name_id
);
250 trie_print_result(tr
);